package edu.hrbu.systemadmin.interceptor;

import cn.hutool.json.JSONUtil;
import edu.hrbu.systemadmin.util.R;
import edu.hrbu.systemadmin.vo.LoginUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.concurrent.TimeUnit;

import static edu.hrbu.systemadmin.util.ConstUtil.*;

/**
 * @author 徐登宇
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    // 注意这里我们不能够通过依赖注入获取到spring中的bean：
    // 1. 这个拦截器并没有纳入到spring容器管理
    // 2. 【网上搜索到的】·拦截器在SpringContext初始化之前就执行了，Bean初始化之前它就执行了，所以它肯定是无法获取SpringIOC容器中的内容的。·
    private StringRedisTemplate stringRedisTemplate;

    public LoginInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

//        log.info("redis::{}", stringRedisTemplate);

        R r = R.builder().code(401).message("Bad Credentials").build();

        // 从请求头获取token
        String token = request.getHeader(HEADER_AUTHORIZATION);

        // token为空，拦截
        if (token == null) {
            response.setStatus(401);
            response.getWriter().println(JSONUtil.toJsonStr(r));
            return false;
        }


        // 从redis通过token获取信息，从请求头中获取userName ==》拼装前缀
        String tokenKey = TOKEN_PREFIX + request.getHeader(HEADER_USERNAME) + ":" + token;
        String cacheLoginUserStr = stringRedisTemplate.opsForValue().get(tokenKey);
        LoginUserVo cacheLoginUser = JSONUtil.toBean(cacheLoginUserStr, LoginUserVo.class);

        // 拦截
        if (cacheLoginUser == null) {
            response.setStatus(401);
            response.getWriter().println(JSONUtil.toJsonStr(r));
            return false;
        }
        String permsKey=PERMS_PREFIX+token;
        String rolesKey=ROLE_PREFIX+token;
        // 如果用户不为空，token、perms、roles续命，放行
        stringRedisTemplate.expire(tokenKey, HALF_TTL, TimeUnit.MINUTES); // token续命【重新设置ttl：30min】

        stringRedisTemplate.expire(permsKey,HALF_TTL,TimeUnit.MINUTES);
        stringRedisTemplate.expire(rolesKey,HALF_TTL,TimeUnit.MINUTES);

        return true;

    }

}
